;;  Copyright (c) Jeffrey Straszheim. All rights reserved.  The use and
;;  distribution terms for this software are covered by the Eclipse Public
;;  License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can
;;  be found in the file epl-v10.html at the root of this distribution.  By
;;  using this software in any fashion, you are agreeing to be bound by the
;;  terms of this license.  You must not remove this notice, or any other,
;;  from this software.
;;
;;  test-rules.clj
;;
;;  A Clojure implementation of Datalog -- Rule Tests
;;
;;  straszheimjeffrey (gmail)
;;  Created 12 Feburary 2009


(ns clojure.datalog.tests.test-rules
  (:use clojure.contrib.test-is
	clojure.datalog.rules)
  (:use [clojure.contrib.except :only (throwf)]))


(def test-rule-1 (logic-rule (:fred  :x ?x :y ?y) -
                             (:mary  :x ?x :z ?z)
                             (:sally :z ?z :y ?y)))

(def test-rule-2 (logic-rule (:fred  :x ?x :y ?y) -
                             (:mary  :x ?x :z ?z)
                             (:sally :z ?z :y ?y)
                             (not! :pat :y ?y)
                             (if < ?x ?y)))


(deftest test-literal-vars
  (is (= (set (-> test-rule-1 :head literal-vars))
         #{'?x '?y})))

(deftest test-body-vars
  (is (= (set (body-vars test-rule-1))
         #{'?x '?y '?z}))
  (is (= (set (body-vars test-rule-2))
         #{'?x '?y '?z})))

(deftest test-negated-vars
  (is (empty? (negated-vars test-rule-1)))
  (is (= (set (negated-vars test-rule-2))
         #{'?y})))

(deftest test-conditional-vars
  (is (empty? (conditional-vars test-rule-1)))
  (is (= (set (conditional-vars test-rule-2))
         #{'?x '?y})))

(deftest test-rule-safe?
  (is (= test-rule-1 (rule-safe? test-rule-1))) ; Silly, really
  (is (= test-rule-2 (rule-safe? test-rule-2))) ; ditto

  (is (thrown-with-msg? Exception #".*non-logic variables as terms.*"
               (logic-rule (:fred :x :y) - (:sally :y :y))))

  (is (thrown-with-msg? Exception #".*unrealized variables.*"
               (logic-rule (:fred :x ?x) - (:sally :y ?y))))

  (is (thrown-with-msg? Exception #".*unsafe negation.*"
               (logic-rule (:fred :x ?x) - (:sally :x ?x) (not! :becky :z ?z))))

  (is (thrown-with-msg? Exception #".*unsafe conditionals.*"
               (logic-rule (:fred :x ?x) - (:sally :x ?x) (if > ?x ?y)))))

(deftest test-rule-relation
  (is (= :fred (rule-relation test-rule-1))))

(deftest test-rule-dependent-relations
  (is (= (rule-dependent-relations test-rule-1)
         #{:mary :sally}))
  (is (= (rule-dependent-relations test-rule-2)
         #{:mary :sally :pat})))

(deftest test-rule-dependent-relations-positive
  (is (= (rule-dependent-relations-positive test-rule-1)
         #{:mary :sally}))
  (is (= (rule-dependent-relations-positive test-rule-2)
         #{:mary :sally})))
  
(deftest test-rule-dependent-relations-negative
  (is (empty? (rule-dependent-relations-negative test-rule-1)))
  (is (= (rule-dependent-relations-negative test-rule-2)
         #{:pat})))
  
(def test-database
     {
      :mary
      #{{:x 1 :z 2} {:x 2 :z 1} {:x 1 :y 2}}

      :sally
      #{{:z 1 :y 2} {:z 2 :y 3} {:z 2 :y 4}}

      :pat
      #{{:y 4}}
      })

(deftest test-match-rule
  (is (= (match-rule test-rule-1 test-database)
         {:fred #{{:y 2, :x 2} {:y 3, :x 1} {:y 4 :x 1}}}))
  (is (= (match-rule test-rule-2 test-database)
         {:fred #{{:y 3, :x 1}}})))

(comment
  (run-tests)
)

;; End of file

